<?php
/**
    A JSONResponse class for getting and setting server-side
    session variables.

    Required message payload structure:

    {
        get: [list of session vars to fetch],
        set: {key1:val1,...},
        clearSession: boolean,
        id: boolean
    }

    All entries are optional, but if no action is specified then
    the response will have a non-0 result code.


    The response payload structure:

    {
        get:{key1:val1...},
        set:{key1:val1,...},
        cleared: true, // IFF clearSession was specified
        id: string // IFF id was specified.
    }

    But the various entries will only be set if the corresponding
    request entry was specified.

    The 'set' result contains the keys/values which were just set.

    If 'get' is set to an empty array then all session vars are
    returned.

    When both get and set are specified, get is performed
    before set. In this case, the response data's "set" field
    contains the new values and the "get" field contains
    the old ones.

    If clearSession is specified, it happens AFTER get but
    BEFORE set.
*/
class JSONResponse_ServerSession extends JSONResponse
{
    /**
        $li must be an array of session keys/vals.
        Returns an array of the set properties.

        e.g. array('mykey' => "foo");
    */
    private function setEnv($li)
    {
        $ar = array();
        if( is_array($_SESSION) )
        {
            if($li) foreach( $li as $k => $v )
            {
                $ar[$k] = $_SESSION[$k] = $v;
            }
        }
        return $ar;
    }
    /**
        $li must be a space- or comma-delimited string, or an array,
        of session var keys. Returns an array of the
        requested properties, or all session props if
        !$li or $li is empty.

        e.g. array('mykey','yourkey','donkey');

        Properties which are not set in the session
        will have null values in the returned array.
    */
    private function getEnv($li)
    {
        if( ! @is_array($li) ) $li = ''.$li;
        if( @is_string($li) ) $li = explode(' ',str_replace(',',' ',$li));
        $ar = array();
        if($li && count($li))
        {
            foreach( $li as $i => $k )
            {
                if( !$k ) continue /*caused by adjacent separators.*/;
                $ar[$k] = $_SESSION[$k];
            }
        }
        else if( is_array($_SESSION) )
        {
            foreach( $_SESSION as $k => $v )
            {
                $ar[$k] = $_SESSION[$k];
            }
        }
        return $ar;
    }
    /**
        See JSONMessage constructor.
    */
    public function __construct( JSONRequest $req )
    {
        parent::__construct( $req );

        if( ! session_id() )
        {
            throw new Exception("Session is not initialized!",1);
        }

        $payload = $req->getPayload(array());
        if( (null != $payload) && !is_array($payload) )
        {
            throw new Exception("Session payload must be null/false/undefined or an object.");
        }
        $ans = array();
        if( @$payload['id'] )
        {
            $ans['id'] = session_id();
        }
        $ar = @$payload['get'];
        $got = 0;
        if( is_array($ar) || is_string($ar) )
        {
            ++$got;
            $ans['get'] = $this->getEnv($ar);
        }
        else
        {
            if( ! is_null($ar) )
            {
                throw new Exception("The 'get' payload field must be a string or array listing the vars to fetch!");
            }
        }
        $ar = @$payload['clearSession'];
        if( $ar )
        {
                ++$got;
                if( is_array($_SESSION) ) $_SESSION = array();
                $ans['cleared'] = true;
                $this->setResult(0,"Session data destroyed.");
        }
        $ar = @$payload['set'];
        if( $ar && is_array($ar) )
        {
            ++$got;
            $ans['set'] = $this->setEnv($ar);
        }
        else
        {
            if( ! is_null($ar) )
            {
                throw new Exception("The 'set' payload field must be an object containing the vars to set!");
            }
        }
        if( ! $got )
        {
            $this->setResult(1,"Usage error: no action specified.");
        }
        else
        {
            $this->setPayload( $ans );
        }
    }
    public static function factory( JSONRequest $req )
    {
        return new JSONResponse_ServerSession($req);
    }

}
JSONMessageDispatcher::mapResponderFile( __FILE__, JSONResponse_ServerSession );

?>
